package com.ruoyi.boat.codec;

import com.ruoyi.boat.domain.PathPoint;
import com.ruoyi.boat.utils.ByteUtil;
import com.ruoyi.common.utils.StringUtils;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class MessageEncode {
    private static AtomicInteger serialNum = new AtomicInteger(0);

    public static int getLastCmdSerialNum(){
        int currentValue = serialNum.get();
        if(currentValue == 0){
            return 0xffff;
        }
        return currentValue - 1;
    }

    private static String generateSerialNum(){
        int serial = serialNum.getAndIncrement();
        if(serial == 0xffff){
            serialNum.set(0);
        }
        return String.format("%04X",serial);
    }
    //创建运行轨迹
    public static byte[] genCreatePathCmd(List<PathPoint> pointList) {
        StringBuilder dataBodyHexSb = new StringBuilder();
        dataBodyHexSb.append(ByteUtil.byteToHex((byte) pointList.size()));
        for (int i = 0; i < pointList.size(); i++) {
            PathPoint point = pointList.get(i);
            dataBodyHexSb.append(ByteUtil.byteToHex((byte)(i+1)));
            double lng = point.getLng();
            dataBodyHexSb.append(StringUtils.leftPad(Integer.toHexString((int)(lng*1000000)),8,'0'));
            double lat = point.getLat();
            dataBodyHexSb.append(StringUtils.leftPad(Integer.toHexString((int)(lat*1000000)),8,"0"));
        }
        byte[] dataBodyBytes = ByteUtil.hexStrToBytes(dataBodyHexSb.toString());
        String dataHeaderSb = "55" + generateSerialNum() + "6922" +
                ByteUtil.calculateCRC16(dataBodyBytes) +
                StringUtils.leftPad(Integer.toHexString(dataBodyHexSb.length()), 4, '0');
        byte[] dataHeaderBytes = ByteUtil.hexStrToBytes(dataHeaderSb);
        return ByteUtil.byteMerger(dataHeaderBytes,dataBodyBytes);
    }

    //追加运行轨迹
    public static byte[] genAppendPathCmd(List<PathPoint> pointList, int existPointNum) {
        StringBuilder dataBodyHexSb = new StringBuilder();
        dataBodyHexSb.append(ByteUtil.byteToHex((byte) pointList.size()));
        for (int i = 0; i < pointList.size(); i++) {
            PathPoint point = pointList.get(i);
            dataBodyHexSb.append(ByteUtil.byteToHex((byte)(++existPointNum)));
            double lng = point.getLng();
            dataBodyHexSb.append(StringUtils.leftPad(Integer.toHexString((int)(lng*1000000)),8,'0'));
            double lat = point.getLat();
            dataBodyHexSb.append(StringUtils.leftPad(Integer.toHexString((int)(lat*1000000)),8,"0"));
        }
        byte[] dataBodyBytes = ByteUtil.hexStrToBytes(dataBodyHexSb.toString());
        String dataHeaderSb = "55" + generateSerialNum() + "6923" +
                ByteUtil.calculateCRC16(dataBodyBytes) +
                StringUtils.leftPad(Integer.toHexString(dataBodyHexSb.length()), 4, '0');
        byte[] dataHeaderBytes = ByteUtil.hexStrToBytes(dataHeaderSb);
        return ByteUtil.byteMerger(dataHeaderBytes,dataBodyBytes);
    }

    //手动模式时可以发送舵角控制指令
    //正舵0x00 左舵0x1e 右舵0x82
    public static byte[] genControlRudderCmd(byte rudderCmd){
        StringBuilder dataBodyHexSb = new StringBuilder();
        dataBodyHexSb.append(ByteUtil.byteToHex(rudderCmd));

        byte[] dataBodyBytes = ByteUtil.hexStrToBytes(dataBodyHexSb.toString());
        String dataHeaderSb = "55" + generateSerialNum() + "6924" +
                ByteUtil.calculateCRC16(dataBodyBytes) +
                StringUtils.leftPad(Integer.toHexString(dataBodyHexSb.length()), 4, '0');
        byte[] dataHeaderBytes = ByteUtil.hexStrToBytes(dataHeaderSb);
        return ByteUtil.byteMerger(dataHeaderBytes,dataBodyBytes);
    }

    //配置平台上报频率
    // 1-255分钟
    public static byte[] genChangeReportFreCmd(int reportFre){
        StringBuilder dataBodyHexSb = new StringBuilder();
        dataBodyHexSb.append(ByteUtil.byteToHex((byte)reportFre));

        byte[] dataBodyBytes = ByteUtil.hexStrToBytes(dataBodyHexSb.toString());
        String dataHeaderSb = "55" + generateSerialNum() + "6925" +
                ByteUtil.calculateCRC16(dataBodyBytes) +
                StringUtils.leftPad(Integer.toHexString(dataBodyHexSb.length()), 4, '0');
        byte[] dataHeaderBytes = ByteUtil.hexStrToBytes(dataHeaderSb);
        return ByteUtil.byteMerger(dataHeaderBytes,dataBodyBytes);
    }

    //修改北斗目标地址
    public static byte[] genChangeBdAddressCmd(String bdAddress){
        StringBuilder dataBodyHexSb = new StringBuilder();
        dataBodyHexSb.append(StringUtils.leftPad(Integer.toHexString(Integer.parseInt(bdAddress)),8,"0"));

        byte[] dataBodyBytes = ByteUtil.hexStrToBytes(dataBodyHexSb.toString());
        String dataHeaderSb = "55" + generateSerialNum() + "6926" +
                ByteUtil.calculateCRC16(dataBodyBytes) +
                StringUtils.leftPad(Integer.toHexString(dataBodyHexSb.length()), 4, '0');
        byte[] dataHeaderBytes = ByteUtil.hexStrToBytes(dataHeaderSb);
        return ByteUtil.byteMerger(dataHeaderBytes,dataBodyBytes);
    }

    /**
     *修改北斗站号
     */
    public static byte[] genChangeDeviceStationCmd(int stationNum){
        StringBuilder dataBodyHexSb = new StringBuilder();
        dataBodyHexSb.append(ByteUtil.byteToHex((byte)stationNum));

        byte[] dataBodyBytes = ByteUtil.hexStrToBytes(dataBodyHexSb.toString());
        String dataHeaderSb = "55" + generateSerialNum() + "6928" +
                ByteUtil.calculateCRC16(dataBodyBytes) +
                StringUtils.leftPad(Integer.toHexString(dataBodyHexSb.length()), 4, '0');
        byte[] dataHeaderBytes = ByteUtil.hexStrToBytes(dataHeaderSb);
        return ByteUtil.byteMerger(dataHeaderBytes,dataBodyBytes);
    }

    /**
     * 配置平台自动/手动模式切换
     * @param type 0x01 手动 0x02 自动
     */
    public static byte[] genCommunicationTypeCmd(int type){
        StringBuilder dataBodyHexSb = new StringBuilder();
        dataBodyHexSb.append(ByteUtil.byteToHex((byte)type));

        byte[] dataBodyBytes = ByteUtil.hexStrToBytes(dataBodyHexSb.toString());
        String dataHeaderSb = "55" + generateSerialNum() + "692A" +
                ByteUtil.calculateCRC16(dataBodyBytes) +
                StringUtils.leftPad(Integer.toHexString(dataBodyHexSb.length()), 4, '0');
        byte[] dataHeaderBytes = ByteUtil.hexStrToBytes(dataHeaderSb);
        return ByteUtil.byteMerger(dataHeaderBytes,dataBodyBytes);
    }

    /**
     * 安全跑偏半径 m
     * @param radius 半径
     */
    public static byte[] genChangeAllowableDeviationRadiusCmd(int radius){
        StringBuilder dataBodyHexSb = new StringBuilder();
        dataBodyHexSb.append(StringUtils.leftPad(Integer.toHexString(radius),4,"0"));

        byte[] dataBodyBytes = ByteUtil.hexStrToBytes(dataBodyHexSb.toString());
        String dataHeaderSb = "55" + generateSerialNum() + "692B" +
                ByteUtil.calculateCRC16(dataBodyBytes) +
                StringUtils.leftPad(Integer.toHexString(dataBodyHexSb.length()), 4, '0');
        byte[] dataHeaderBytes = ByteUtil.hexStrToBytes(dataHeaderSb);
        return ByteUtil.byteMerger(dataHeaderBytes,dataBodyBytes);
    }

    /**
     * 数据自毁
     * @param flag 1自毁 0 正常
     */
    public static byte[] genDataSelfDestroyCmd(int flag){
        StringBuilder dataBodyHexSb = new StringBuilder();
        dataBodyHexSb.append(ByteUtil.byteToHex((byte)flag));

        byte[] dataBodyBytes = ByteUtil.hexStrToBytes(dataBodyHexSb.toString());
        String dataHeaderSb = "55" + generateSerialNum() + "7921" +
                ByteUtil.calculateCRC16(dataBodyBytes) +
                StringUtils.leftPad(Integer.toHexString(dataBodyHexSb.length()), 4, '0');
        byte[] dataHeaderBytes = ByteUtil.hexStrToBytes(dataHeaderSb);
        return ByteUtil.byteMerger(dataHeaderBytes,dataBodyBytes);
    }

    /**
     * 电机转速设置
     * @param flag 2高速 1 低速 0 关闭
     */
    public static byte[] genRotationCmd(int flag){
        StringBuilder dataBodyHexSb = new StringBuilder();
        dataBodyHexSb.append(ByteUtil.byteToHex((byte)flag));

        byte[] dataBodyBytes = ByteUtil.hexStrToBytes(dataBodyHexSb.toString());
        String dataHeaderSb = "55" + generateSerialNum() + "6A72" +
                ByteUtil.calculateCRC16(dataBodyBytes) +
                StringUtils.leftPad(Integer.toHexString(dataBodyHexSb.length()), 4, '0');
        byte[] dataHeaderBytes = ByteUtil.hexStrToBytes(dataHeaderSb);
        return ByteUtil.byteMerger(dataHeaderBytes,dataBodyBytes);
    }

    /**
     * 舰体脱钩
     * @param flag 1脱钩 0 正常
     */
    public static byte[] genHullDecouplingCmd(int flag){
        StringBuilder dataBodyHexSb = new StringBuilder();
        dataBodyHexSb.append(ByteUtil.byteToHex((byte)flag));

        byte[] dataBodyBytes = ByteUtil.hexStrToBytes(dataBodyHexSb.toString());
        String dataHeaderSb = "55" + generateSerialNum() + "7922" +
                ByteUtil.calculateCRC16(dataBodyBytes) +
                StringUtils.leftPad(Integer.toHexString(dataBodyHexSb.length()), 4, '0');
        byte[] dataHeaderBytes = ByteUtil.hexStrToBytes(dataHeaderSb);
        return ByteUtil.byteMerger(dataHeaderBytes,dataBodyBytes);
    }

    /**
     * 绞车启动
     * @param flag 1启动 0 正常
     */
    public static byte[] genWinchStartCmd(int flag){
        StringBuilder dataBodyHexSb = new StringBuilder();
        dataBodyHexSb.append(ByteUtil.byteToHex((byte)flag));

        byte[] dataBodyBytes = ByteUtil.hexStrToBytes(dataBodyHexSb.toString());
        String dataHeaderSb = "55" + generateSerialNum() + "7923" +
                ByteUtil.calculateCRC16(dataBodyBytes) +
                StringUtils.leftPad(Integer.toHexString(dataBodyHexSb.length()), 4, '0');
        byte[] dataHeaderBytes = ByteUtil.hexStrToBytes(dataHeaderSb);
        return ByteUtil.byteMerger(dataHeaderBytes,dataBodyBytes);
    }

    /**
     * 回收浮块释放
     * @param flag 1释放 0 正常
     */
    public static byte[] genFloatBlockReleaseCmd(int flag){
        StringBuilder dataBodyHexSb = new StringBuilder();
        dataBodyHexSb.append(ByteUtil.byteToHex((byte)flag));

        byte[] dataBodyBytes = ByteUtil.hexStrToBytes(dataBodyHexSb.toString());
        String dataHeaderSb = "55" + generateSerialNum() + "7924" +
                ByteUtil.calculateCRC16(dataBodyBytes) +
                StringUtils.leftPad(Integer.toHexString(dataBodyHexSb.length()), 4, '0');
        byte[] dataHeaderBytes = ByteUtil.hexStrToBytes(dataHeaderSb);
        return ByteUtil.byteMerger(dataHeaderBytes,dataBodyBytes);
    }

    /**
     * 声光报警
     * @param flag 1报警 0 正常
     */
    public static byte[] genAudioVisualAlarmCmd(int flag){
        StringBuilder dataBodyHexSb = new StringBuilder();
        dataBodyHexSb.append(ByteUtil.byteToHex((byte)flag));

        byte[] dataBodyBytes = ByteUtil.hexStrToBytes(dataBodyHexSb.toString());
        String dataHeaderSb = "55" + generateSerialNum() + "7925" +
                ByteUtil.calculateCRC16(dataBodyBytes) +
                StringUtils.leftPad(Integer.toHexString(dataBodyHexSb.length()), 4, '0');
        byte[] dataHeaderBytes = ByteUtil.hexStrToBytes(dataHeaderSb);
        return ByteUtil.byteMerger(dataHeaderBytes,dataBodyBytes);
    }

    public static byte[] genLoadCmd(int switchValue){
        StringBuilder dataBodyHexSb = new StringBuilder();
        dataBodyHexSb.append(ByteUtil.byteToHex((byte)switchValue));

        byte[] dataBodyBytes = ByteUtil.hexStrToBytes(dataBodyHexSb.toString());
        String dataHeaderSb = "55" + generateSerialNum() + "7926" +
                ByteUtil.calculateCRC16(dataBodyBytes) +
                StringUtils.leftPad(Integer.toHexString(dataBodyHexSb.length()), 4, '0');
        byte[] dataHeaderBytes = ByteUtil.hexStrToBytes(dataHeaderSb);
        return ByteUtil.byteMerger(dataHeaderBytes,dataBodyBytes);
    }
}
